////////////////////////////////////////////////////////////////////////////////

#ifndef _CLIENTNETWORK_H_
#include "clientnetwork.h"
#endif

////////////////////////////////////////////////////////////////////////////////

#ifndef _CLIENT_H_
#include "client.h"
#endif

#ifndef _NETWORKPACKET_H_
#include "networkpacket.h"
#endif

#ifndef _CLIENTPACKETFACTORY_H_
#include "clientpacketfactory.h"
#endif

#ifndef _CLIENTINFOPACKET_H_
#include "clientinfopacket.h"
#endif

#ifndef _CLIENTINPUTPACKET_H_
#include "clientinputpacket.h"
#endif

#ifndef _SAVER_H_
#include "saver.h"
#endif

#ifndef _BOOSTSERVICE_H_
#include "boostservice.h"
#endif

#include <cassert>
#include <iostream>

////////////////////////////////////////////////////////////////////////////////


ClientNetwork::ClientNetwork()
: m_Connection(Connection::CLIENT)
{
    // Setup observer
    AddEventToObserve( Observer::NETWORK_SEND_COMPLETE_TCP );
    AddEventToObserve( Observer::NETWORK_SEND_COMPLETE_UDP );
    AddEventToObserve( Observer::NETWORK_RECEIVE_COMPLETE_TCP );
    AddEventToObserve( Observer::NETWORK_RECEIVE_COMPLETE_UDP );

    m_Connection.AddObserver(this);
}


////////////////////////////////////////////////////////////////////////////////


ClientNetwork::~ClientNetwork()
{
    m_Connection.RemoveObserver(this);
}


////////////////////////////////////////////////////////////////////////////////


void ClientNetwork::Connect()
{
    // Get server address
    // std::cout<<"Server: ";

    std::string address = "localhost";

    //std::cin>>address;

    try
    {
        // Connect to server
        m_Connection.Connect( address.c_str() );
    }
    catch (...)
    {
        std::cout<<"Server not found"<<std::endl;
    }

    ClientInfoPacket packet( ClientInfo("NickName") );
    SendClientInfo(packet);
}


////////////////////////////////////////////////////////////////////////////////


void ClientNetwork::HandleReceive()
{
    // Get received data
    Buffer recvBuffer( m_Connection.GetRecvDataUDP().Data(), m_Connection.GetRecvDataUDP().Size() );

    // Compose packet from it
    ServerPacketOnClient* packet = ClientPacketFactory::ComposePacket(recvBuffer);

    // Redirect it to client
    m_Client->Receive(packet);
}


////////////////////////////////////////////////////////////////////////////////


void ClientNetwork::Start( Client* _client )
{
    m_Client = _client;
    Connect();
    BoostService::Run();
}


////////////////////////////////////////////////////////////////////////////////


void ClientNetwork::OnEvent( Event _event, Observable* _observable )
{
    switch (_event)
    {
    case Observer::NETWORK_RECEIVE_COMPLETE_TCP:
    case Observer::NETWORK_RECEIVE_COMPLETE_UDP:
        HandleReceive();
        break;

    default:
        break;
    }
}


////////////////////////////////////////////////////////////////////////////////


bool ClientNetwork::IsConnected() const
{
    return m_Connection.IsConnected();
}


////////////////////////////////////////////////////////////////////////////////


void ClientNetwork::SendClientInfo( const ClientInfoPacket& _clientInfoPacket )
{
    Saver saver;
    saver.SaveClientInfoPacket(_clientInfoPacket);

    NetworkPacket packet( saver.GetBuffer().Data(), saver.GetBuffer().Size() );
    m_Connection.SendTCP(packet);
}


////////////////////////////////////////////////////////////////////////////////


void ClientNetwork::SendClientInput( const ClientInputPacket& _clientInputPacket )
{
    Saver saver;
    saver.SaveClientInputPacket(_clientInputPacket);

    NetworkPacket packet( saver.GetBuffer().Data(), saver.GetBuffer().Size() );
    m_Connection.SendUDP(packet);
}


////////////////////////////////////////////////////////////////////////////////
